package com.joinway.framework.data.adaptor.mybatis.repository;

import java.util.List;

import org.apache.commons.beanutils.MethodUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.joinway.framework.data.adaptor.bean.PageRecord;
import com.joinway.framework.extension.utils.NumberUtils;

public class PagableRepository {

	private final static Logger log = LoggerFactory.getLogger(PagableRepository.class);
	
	private int defaultPage = 1;
	
	private int defaultRows = 10;
	
	public<T, E, M> PageRecord<T> findRecordByExample(M mapper, E example, int page, int rows, String defaultOrderByClause, Class<T> type) throws Exception {
		return findRecordByExample(mapper, example, page, rows, defaultOrderByClause, type, false);
	}
	
//	public<T, E, M> PageRecord<T> findRecordByExample(M mapper, E example, int page, int rows, String defaultOrderByClause, Class<T> type, boolean blob) throws Exception {
//		return findRecordByExample(mapper, example, page, rows, defaultOrderByClause, type, blob, null);
//	}
//	
//	public<T, E, M, V> PageRecord<T> findRecordByExample(M mapper, E example, int page, int rows, String defaultOrderByClause, Class<T> type, ValueBuilder<T, V> builder) throws Exception {
//		return findRecordByExample(mapper, example, page, rows, defaultOrderByClause, type, false, builder);
//	}
	
	/**
	 * 
	 * @param mapper	mybatis mapper对象
	 * @param example	mybatis example对象
	 * @param page		页号
	 * @param rows		每页行数
	 * @param defaultOrderByClause	默认排序字句，如 id asc
	 * @param type	返回值类型
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public<T, E, M, V> PageRecord<T> findRecordByExample(M mapper, E example, int page, int rows, String defaultOrderByClause, Class<T> type, boolean blob) throws Exception {
		PageRecord<T> record = new PageRecord<>();
		
		Object orderBy = MethodUtils.invokeExactMethod(example, "getOrderByClause", null);
		int targetPage = page <= 0 ? defaultPage : page;
		int targetRows = rows <= 0 ? defaultRows : rows;
		
		record.setCurrentPage(targetPage);
		
		try{
			int count = (int)MethodUtils.invokeExactMethod(mapper, "countByExample", example);
			record.setTotalPage(NumberUtils.dividePlusMod(count, targetRows));
			record.setRecordCount(count);
			
			String limitClause = " limit " + (targetPage - 1) * targetRows + ", " + targetRows;
			String pagableClause = orderBy != null && StringUtils.isNotBlank(orderBy.toString())? orderBy.toString() + limitClause : defaultOrderByClause + limitClause;
			
			MethodUtils.invokeExactMethod(example, "setOrderByClause", pagableClause);
			String selectMethod = blob ? "selectByExampleWithBLOBs" : "selectByExample";
			List<T> domains = (List<T>)MethodUtils.invokeExactMethod(mapper, selectMethod, example);
			record.setRows(domains);
			
//			if(builder != null && CollectionUtils.isNotEmpty(domains)){
//				for(T t : domains){
//					builder.build(t);
//				}
//			}
		}catch(Exception e){
			log.error("failed to make page", e);
			if(orderBy != null && StringUtils.isNotBlank(orderBy.toString())){
				MethodUtils.invokeExactMethod(example, "setOrderByClause", orderBy);
			}
		}
		
		return record;
	}

	public int getDefaultPage() {
		return defaultPage;
	}

	public void setDefaultPage(int defaultPage) {
		this.defaultPage = defaultPage;
	}

	public int getDefaultRows() {
		return defaultRows;
	}

	public void setDefaultRows(int defaultRows) {
		this.defaultRows = defaultRows;
	}
}

